﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Collections.Generic
{
    public static  class LinkListExtention
    {
        /// <summary>
        /// 对于所有 LinkList&lt;T[]&gt; 中数组节点 按照顺序  进行从头开始的枚举
        /// </summary>
        /// <typeparam name="T">节点中数组元素的类型</typeparam>
        /// <param name="linklist">枚举的目标</param>
        /// <returns>可枚举的内容</returns>
        static public IEnumerable<T> GetNodesJoinedEnumerable<T> ( this LinkedList <T[]> linklist)
        {
            var tn = linklist.First;
            while (tn != null)
            {
                foreach (var t in tn.Value)
                {
                    yield return t;
                }
                tn = tn.Next;
            }            
        
        }
        /// <summary>
        /// 检查LinkedList&lt;T[]&gt; 中是否存在足够的元素
        /// </summary>
        /// <typeparam name="T">节点中数组元素的类型</typeparam>
        /// <param name="linklist">检查的目标</param>
        /// <param name="count">枚举个数</param>
        /// <returns>是否足够</returns>
        public static bool CheckHaveEnoughItems<T>(this LinkedList<T[]> linklist, int count)
        {
            int tcount = 0;
            var tn = linklist.First;
            while (tn != null)
            {
                tcount = tcount + tn.Value.Length;
                if (tcount >= count) return true;

                tn = tn.Next;
            }
            return false;
        
        }

        /// <summary>
        /// 把 LinkedList&lt;T[]&gt; 当作整个T[]的数组 从头复制下count长的一部分
        /// </summary>
        /// <typeparam name="T">节点中数组元素的类型</typeparam>
        /// <param name="linklist">检查的目标</param>
        /// <param name="count">枚举个数</param>
        /// <returns>复制得到的数组</returns>
        public static T[] PeekNodesFromNodeLists<T>(this LinkedList<T[]> linklist, int count)
        {
            var countWork = count;
            var tn = linklist.First;
            List<T[]> tl = new List<T[]>();
            while (tn != null)
            {

                countWork = countWork - tn.Value.Length;
                if (countWork > 0)
                {
                    tl.Add(linklist.First.Value);
                    linklist.RemoveFirst();
                }


                else if (countWork <= 0)
                {
                    T[] rval = new T[countWork];
                    int progi = 0;
                    foreach (var ary in tl)
                    {
                        if (progi + ary.Length <= count)
                        {
                            Array.Copy(ary, 0, rval, progi, ary.Length);
                            progi = progi + ary.Length;
                        }
                        else
                        {
                            Array.Copy(ary, 0, rval, progi, progi + ary.Length - count);
                            progi = progi + ary.Length;
                        }
                    }

          

                    return rval;

                }


                tn = tn.Next;
            }
            return new T[] { };
        }

      /// <summary>
        /// 把 LinkedList&lt;T[]&gt; 当作整个T[]的数组  从头部切下count长的一部分
      /// </summary>
        /// <typeparam name="T">节点中数组元素的类型</typeparam>
        /// <param name="linklist">检查的目标</param>
        /// <param name="count">枚举个数</param>
        /// <returns>剪切得到的数组</returns>
        public static T[]  FrontCutNodesFromNodeLists<T>(this LinkedList<T[]> linklist, int count)
        {
            var countWork=count;
            var tn = linklist.First;
            List<T[]> tl=new  List<T[]>();
            while (tn != null)
            {
                
                countWork = countWork - tn.Value.Length;
                if (countWork > 0)
                {
                    tl.Add(linklist.First.Value);
                    linklist.RemoveFirst();
                }


                else if (countWork <= 0)
                {
                    T[] rval = new T[countWork];
                    int progi = 0;
                    foreach (var ary in tl)
                    {
                        if (progi + ary.Length <= count)
                        {
                            Array.Copy(ary, 0, rval, progi, ary.Length);
                            progi = progi + ary.Length;
                        }
                        else 
                        {
                            Array.Copy(ary, 0, rval, progi, progi+ ary.Length -count );
                            progi = progi + ary.Length;
                        }
                    }

                    if (countWork < 0)
                    {
                        T[] tTs = new T[countWork + tn.Value.Length];
                        Array.Copy(tn.Value, -countWork - 1, tTs, 0, tTs.Length);

                        linklist.RemoveFirst();
                        linklist.AddFirst(tTs);
                    }
                    

                    return rval;

                }


                tn = tn.Next;
            }
            return  new T[]{};
        }

        static public IEnumerable<LinkedListNode<T>> GetDescEnumerable<T>(this LinkedList<T> linklist) 
        {
            return linklist.Last.GetMidwayEnumerable(LinkListNodeExtention.EnumerateDirection.Backward, true);
        }
    }


    

}
